#include "CSMsgDef.h"
#include "CTArray.h"
#include "CTBuffer.h"
#include "net/CTSocket.h"
#include "base/CTFile.h"

#include "commmsg.h"

#include "PBMsgHead.pb.h"
#include "MsgOfficeGM.pb.h"

using namespace CTLib;

#define SVR_VERSION 1000
#define BUFF_LENGTH 10240
#define ROLENAME_LEN 20

bool IsAllNum(const char* s)
{
	for (int i = 0; i < (int)strlen(s); ++i)
	{
		if (s[i] < '0' || s[i] > '9')
		{
			return false;
		}
	}
	
	return true;
}

int SetMsgHead(PBMsgHead& stMsgHead, MsgReqOfficeGM& stReq, int argc,
        char* argv[])
{
    stMsgHead.set_version(SVR_VERSION);
    stMsgHead.set_time((int)time(NULL));
    stMsgHead.set_msgact(0);
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgtype(CSMsgDef::EMT_REQUEST);
    stMsgHead.set_msgid(ID_MAIN_GM_OFFICE);

    if (argc < 4)
    {
        return -1;
    }

    //参数列表：
    //argv[1]:IP argv[2]:Port argv[3]:SubCmd
    //当参数个数大于等于4时候才需要依据SubCmd个性化处理
    //若不个性化处理 默认逻辑:判断argv[4]参数是Token还是GID还是昵称 剩余参数放入int数组

    int iRet = 0;
    int iSubCmd = (int)atoi(argv[3]);

    stReq.set_sub_type(iSubCmd);

    if (argc >= 5)
    {
        if (ID_GM_OFFICE_SUB_SEND_SYS_NOTICE == iSubCmd)//发送系统公告 这里读取一个文件作为输入内容
        {
            CTReadFile stReadFile;
            iRet = stReadFile.Open(argv[4]);
            if (iRet){return iRet;}
            stReq.set_name(stReadFile.ReadLine());
        }
        else if (ID_GM_OFFICE_SUB_SYS_STOP_NOTICE == iSubCmd)//系统停机维护
        {
            if (argc < 6)
            {
                return -1;
            }

			stReq.set_rolename(argv[4]);
			stReq.set_usertoken(argv[5]);
            return 0;
        }
        else if (ID_GM_OFFICE_SUB_SEND_BATCH_GIFTS == iSubCmd)//批量发送礼包
        {
            stReq.set_role_level_limit(atoi(argv[4]));//等级限制值
        }
        else if (ID_GM_OFFICE_SUB_STOP_OPEN_REGIST == iSubCmd ||
                 ID_GM_OFFICE_SUB_STOP_CREATE_CLAN == iSubCmd)
        {
            //设置服务器停止开放注册
            //设置服务器停止创建家族
            stReq.add_datas(atoi(argv[4]));
        }
        else
        {
            CTSizeString<1024> szSizeStr;
            szSizeStr.Set("%s", argv[4]);

            if (szSizeStr.GetDataLen() == 32)//argv[4]是UserToken
            {
				stReq.set_usertoken(argv[4]);
            }
            else if (CTStringUtils::StrToIntVerify(szSizeStr(), true))//argv[4]是GID
            {
				stReq.set_gid((unsigned int)atoi(argv[4]));
            }
            else
            {
				stReq.set_rolename(argv[4]);
            }
        }
        
        for (int i = 5; i < argc; ++i)
        {
            stReq.add_datas(atoi(argv[i]));
        }
    }

    return 0;
}

int Encode(PBMsgHead& stMsgHead, MsgReqOfficeGM& stReq, char* buff,
        int& iDataLength)
{
    int iMsgHeadLen = stMsgHead.ByteSize();
    *(int*)(buff + sizeof(int)) = (int)htonl((int)iMsgHeadLen);
    stMsgHead.SerializeToArray((void*)(buff + sizeof(int) + sizeof(int)),
        stMsgHead.ByteSize());

    int iMsgBodyLen = stReq.ByteSize();
    *(int*)(buff + sizeof(int) + sizeof(int) + iMsgHeadLen) =
        (int)htonl((int)iMsgBodyLen);
    stReq.SerializeToArray((void*)(buff + sizeof(int) + sizeof(int) +
        iMsgHeadLen + sizeof(int)), stReq.ByteSize());

    *(char*)(buff + sizeof(int)*3 + iMsgHeadLen + iMsgBodyLen) = '\t';
    iDataLength = sizeof(int)*3 + iMsgHeadLen + iMsgBodyLen + sizeof(char);

    *(int*)(buff) = (int)htonl((int)iDataLength);

    return 0;
}

int Decode(PBMsgHead& stMsgHead, MsgAnsOfficeGM& stAns, char* buff,
        int& iDataLength)
{
    int iMsgTotalLen = ntohl(*(int*)buff);
    int iMsgHeadLen = ntohl(*(int*)(buff+sizeof(int)));
    int iMsgBodyLen = ntohl(*(int*)(buff+sizeof(int)+sizeof(int)+iMsgHeadLen));
    if (iMsgTotalLen <= 0)
    {
        printf("msglen error(%d)!\n",iMsgTotalLen);
        return -1;
    }
    if (buff[iMsgTotalLen - 1] != '\t')
    {
        printf("flag error(%d)!\n",buff[iMsgTotalLen - 1]);
        return -1;
    }
    
    stMsgHead.ParseFromArray((void*)(buff+sizeof(int)+sizeof(int)),
        iMsgHeadLen);

	if (stMsgHead.msgret() == 0)
    {
        stAns.ParseFromArray((void*)(buff + sizeof(int) + sizeof(int)
            + iMsgHeadLen + sizeof(int)), iMsgBodyLen);
    }

    return 0;
}

int OutputAns(PBMsgHead& stMsgHead, MsgAnsOfficeGM& stAns)
{
	if (stMsgHead.msgret() == 0)
	{	
        for (int i = 0; i < stAns.str_data_size(); ++i)
        {
            printf("%s\n",stAns.str_data(i).c_str());
        }

        if (stAns.str_data_size() <= 0)
        {
            printf("OK!\n");
        }
	}
    else
    {
        printf("Error Ret=%d!\n", stMsgHead.msgret());
    }
	
    return 0;
}

void PrintHelp(char *argv[])
{
    printf("%s ip port cmd [name|argu1]\n",argv[0]);
}

int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        PrintHelp(argv);
        return 0;
    }

    int iRet = 0;
    CTSocket sSocket;
    iRet = sSocket.Connect(argv[1], atoi(argv[2]));
    if (iRet != 0)
    {
        printf("Connect error!\n");
        return -1;
    }

    char buff[BUFF_LENGTH] = {0};

    PBMsgHead stMsgHead;
    MsgReqOfficeGM stReq;
    MsgAnsOfficeGM stAns;

    int iSendlen = 0;
    int iDataLength = 0;

    iRet = SetMsgHead(stMsgHead, stReq, argc, argv);
    if (iRet)
    {
        printf("SetMsgHead error(%d)!\n",iRet);
        return iRet;
    }

    iRet = Encode(stMsgHead, stReq, buff, iDataLength);
    if (iRet)
    {
        printf("Encode error(%d)!\n",iRet);
        return iRet;
    }

    iRet = sSocket.SendEx(buff, iDataLength, iSendlen);
    if (iRet)
    {
        printf("SendEx error(%d)!\n",iRet);
        return iRet;
    }

    sSocket.Recv(buff, BUFF_LENGTH, iSendlen);
    
    iRet = Decode(stMsgHead, stAns, buff, iDataLength);
    if (iRet)
    {
        printf("Decode error(%d)!\n",iRet);
        return iRet;
    }

    iRet = OutputAns(stMsgHead, stAns);
    if (iRet)
    {
        printf("OutputAns error(%d)!\n",iRet);
        return iRet;
    }

    return 0;
}

